package com.liu.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.liu.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.net.SocketTimeoutException;
import java.util.*;

@RestController
public class OrderController {

    @Autowired
    StockService service;
    /**
     * blockHandlerClass  = 指定一场场粗粒的方法所在的类  如果目标资源与处理异常的方法在同一个类中  这个参数可以忽略
     * blockHandler = "handlerBlockException"  指定处理Block异常的方法名称
     * fallback  =  异常降级处理
     * @return
     */
    @GetMapping("/order")
    @SentinelResource(value = "查询订单",fallback = "fallback")
    public Map get(){

        return getOrder2();
    }
    //@PostConstruct  //当控制类启动，就初始化此方法
    void addRlowRules(){
        //定义一组流控规则
        List<FlowRule> list = new ArrayList<>();
        //定义规则
        FlowRule flowRule = new FlowRule("查询订单");
        flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS);  //指定阈值类型
        flowRule.setCount(2);//阈值
        flowRule.setLimitApp("default");//限定请求的来源  限制从哪些服务发来的请求
        list.add(flowRule);
        FlowRuleManager.loadRules(list);

    }

    @PostMapping("/order")
    public  Map save(){
        Map map =new HashMap();
        map.put("msg","生成订单");
        map.put("stock",service.queryStock());
        return map;
    }



    /**
     * 访问目标资源出现异常时  执行在 这里的逻辑
     * @param e
     * @return
     */
    public Map fallback(Throwable e){
        Map map =new HashMap();
        map.put("code","0");
        map.put("msg",e.toString());
        return map;
    }



    /**
     * 降级处理 当了流量超过限定值时  抛出BlockException异常  执行这个方法
     * @param e
     * @return
     */
    public Map handlerBlockException(BlockException e){
        System.out.println("--------------handlerBlockException-----------------");
        Map map =new HashMap();
        map.put("code","100");
        map.put("msg","注解降级处理");
        return map;
    }




    /**
     * 通过SphO  手动定义资源
     * @return
     */
    Map getOrder2(){
        Map map =new HashMap();
        if(SphO.entry("getOrder2")){
            //没有限流  在正常处理
            map.put("orderNum","asdf");
            map.put("money",3999);

            //最后释放资源
            SphO.exit();
        }else{
            //服务限流处理
            map.put("code","100");
            map.put("msg","您的服务开小差了。。。。");
        }
        return map;
    }




    /**
     * 使用 SphU  定义资源  SphU  是类名  使用  try catch  定义资源
     * @return
     */
     Map getOrder(){
        Entry entry = null;
        Map map = null;
        try {
            entry  = SphU.entry("getOrder");  //定义资源
            //资源的核心逻辑
            map =new HashMap();
            map.put("orderNum","asdf");
            map.put("money",2123);
        }catch(BlockException e){
            //throw new RuntimeException(e);
            map.put("code","200");
            map.put("msg","您的服务开小差了。。。。");
        }finally {
            if(null !=entry)
                entry.exit();;
        }
        return  map;
    }



}
